package juc.executors;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * RejectedExecutionHandler handler 执行时被阻塞的策略，当超出最大线程数和队列容量
 * RejectedExecutionException#setRejectedExecutionHandler(RejectedExecutionHandler handler)
 *
 * 1.AbortPolicy 容量满没有空间放线程时就抛出异常，后边的代码不执行
 * 2.DiscardPolicy 直接放弃什么都不执行，后边的代码会执行
 * 3.DiscardOldestPolicy 把队列里的移除，再执行当前线程
 * 4.CallerRunsPolicy 如果没有isShutdown()，main线程就执行run()，没有用的线程池里的线程
 */
public class ExecutorServiceExample2 {

    public static void main(String[] args) {
        //testAbortPolicy();
        //testDiscardPolicy();
        //testCallerRunsPolicy();
        testDiscardOldestPolicy();
    }

    private static void testAbortPolicy() {
        ExecutorService executorService = new ThreadPoolExecutor(1, 2, 7, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1), r -> {
            Thread thread = new Thread(r);
            return thread;
        }, new ThreadPoolExecutor.AbortPolicy());
        for (int i = 0; i < 3; i++) {
            executorService.execute(() -> {
                timeSleep(100);
            });
        }
        timeSleep(1);
        //RejectedExecutionException
        executorService.execute(() -> System.out.println("todo"));
        System.out.println("======");
    }

    private static void testDiscardPolicy() {
        ExecutorService executorService = new ThreadPoolExecutor(1, 2, 7, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1), r -> {
            Thread thread = new Thread(r);
            return thread;
        }, new ThreadPoolExecutor.DiscardPolicy());
        for (int i = 0; i < 3; i++) {
            executorService.execute(() -> {
                timeSleep(100);
            });
        }
        timeSleep(1);
        executorService.execute(() -> System.out.println("todo"));
        System.out.println("======");
    }

    private static void testCallerRunsPolicy() {
        ExecutorService executorService = new ThreadPoolExecutor(1, 2, 7, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1), r -> {
            Thread thread = new Thread(r);
            return thread;
        }, new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < 3; i++) {
            executorService.execute(() -> {
                timeSleep(100);
            });
        }
        timeSleep(1);
        executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " todo"));
        System.out.println("======");
    }

    private static void testDiscardOldestPolicy() {
        ExecutorService executorService = new ThreadPoolExecutor(1, 2, 7, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1), r -> {
            Thread thread = new Thread(r);
            return thread;
        }, new ThreadPoolExecutor.DiscardOldestPolicy());
        for (int i = 0; i < 3; i++) {
            executorService.execute(() -> {
                System.out.println(Thread.currentThread().getName() + " from lambda");
                timeSleep(3);
            });
        }
        timeSleep(1);
        executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " todo"));
        System.out.println("======");
    }

    private static void timeSleep(long time) {
        try {
            TimeUnit.SECONDS.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
